home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / inetray / clnt_dirbcast.c < prev    next >
C/C++ Source or Header  |  1993-08-15  |  7KB  |  242 lines

  1. /*======================================================================
  2.                     C L N T _ D I R B C A S T . C 
  3.                     doc: Tue Jun  2 13:49:18 1992
  4.                     dlm: Thu Jul 22 15:28:54 1993
  5.                     (c) 1992 ant@ips.id.ethz.ch
  6.                     uE-Info: 120 34 T 0 0 72 2 2 8 ofnI
  7. ======================================================================*/
  8.  
  9. /* 
  10.    This file implements a directed broadcast. It's basically a copy of
  11.    the original RPC 4.0 clnt_broadcast routine. A lot of stuff could have
  12.    been thrown out, but I preferred minimum change.
  13. */
  14. /*
  15.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  16.  * unrestricted use provided that this legend is included on all tape
  17.  * media and as a part of the software program in whole or part.  Users
  18.  * may copy or modify Sun RPC without charge, but are not authorized
  19.  * to license or distribute it to anyone else except as part of a product or
  20.  * program developed by the user.
  21.  * 
  22.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  23.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  24.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  25.  * 
  26.  * Sun RPC is provided with no support and without any obligation on the
  27.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  28.  * modification or enhancement.
  29.  * 
  30.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  31.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  32.  * OR ANY PART THEREOF.
  33.  * 
  34.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  35.  * or profits or other special, indirect and consequential damages, even if
  36.  * Sun has been advised of the possibility of such damages.
  37.  * 
  38.  * Sun Microsystems, Inc.
  39.  * 2550 Garcia Avenue
  40.  * Mountain View, California  94043
  41.  */
  42.  
  43. #include <stdio.h>
  44. #include <errno.h>
  45. #include <rpc/rpc.h>
  46. #include <rpc/pmap_rmt.h>
  47. #include <rpc/pmap_prot.h>
  48. #include <sys/socket.h>
  49. #include <netdb.h>        /* Prefer system over rpc/netdb.h */
  50. #include <string.h>
  51. #ifndef ITIMER_REAL
  52. #include     <sys/time.h>
  53. #endif
  54.  
  55. typedef bool_t (*resultproc_t)();
  56.  
  57. enum clnt_stat 
  58. clnt_dirbcast(addr, prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
  59.     char        *addr;        /* internet address */
  60.     u_long        prog;        /* program number */
  61.     u_long        vers;        /* version number */
  62.     u_long        proc;        /* procedure number */
  63.     xdrproc_t    xargs;        /* xdr routine for args */
  64.     caddr_t        argsp;        /* pointer to args */
  65.     xdrproc_t    xresults;    /* xdr routine for results */
  66.     caddr_t        resultsp;    /* pointer to results */
  67.     resultproc_t    eachresult;    /* call with each result obtained */
  68. {
  69.     enum clnt_stat stat;
  70.     AUTH *unix_auth = authunix_create_default();
  71.     XDR xdr_stream;
  72.     register XDR *xdrs = &xdr_stream;
  73.     int outlen, inlen, fromlen, nets;
  74.     register int sock;
  75.     int on = 1;
  76. #ifdef FD_SETSIZE
  77.     fd_set mask;
  78.     fd_set readfds;
  79. #else
  80.     int readfds;
  81.     register int mask;
  82. #endif /* def FD_SETSIZE */
  83.     register int i;
  84.     bool_t done = FALSE;
  85.     register u_long xid;
  86.     u_long port;
  87.     struct in_addr addrs[20];
  88.     struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
  89.     struct rmtcallargs a;
  90.     struct rmtcallres r;
  91.     struct rpc_msg msg;
  92.     struct timeval t;
  93. #define MAX_BROADCAST_SIZE 1400
  94.     char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
  95.  
  96.     /*
  97.      * initialization: create a socket, a broadcast address, and
  98.      * preserialize the arguments into a send buffer.
  99.      */
  100.     if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  101.         perror("Cannot create socket for broadcast rpc");
  102.         stat = RPC_CANTSEND;
  103.         goto done_broad;
  104.     }
  105. #ifdef SO_BROADCAST
  106.     if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
  107.         perror("Cannot set socket option SO_BROADCAST");
  108.         stat = RPC_CANTSEND;
  109.         goto done_broad;
  110.     }
  111. #endif /* def SO_BROADCAST */
  112. #ifdef FD_SETSIZE
  113.     FD_ZERO(&mask);
  114.     FD_SET(sock, &mask);
  115. #else
  116.     mask = (1 << sock);
  117. #endif /* def FD_SETSIZE */
  118.     addrs[0].s_addr = inet_addr(addr);
  119.     nets = 1;
  120.     memset((char *)&baddr, 0, sizeof (baddr));
  121.     baddr.sin_family = AF_INET;
  122.     baddr.sin_port = htons(PMAPPORT);
  123.     baddr.sin_addr.s_addr = htonl(INADDR_ANY);
  124. /*    baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
  125.     (void)gettimeofday(&t, (struct timezone *)0);
  126.     msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
  127.     t.tv_usec = 0;
  128.     msg.rm_direction = CALL;
  129.     msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  130.     msg.rm_call.cb_prog = PMAPPROG;
  131.     msg.rm_call.cb_vers = PMAPVERS;
  132.     msg.rm_call.cb_proc = PMAPPROC_CALLIT;
  133.     msg.rm_call.cb_cred = unix_auth->ah_cred;
  134.     msg.rm_call.cb_verf = unix_auth->ah_verf;
  135.     a.prog = prog;
  136.     a.vers = vers;
  137.     a.proc = proc;
  138.     a.xdr_args = xargs;
  139.     a.args_ptr = argsp;
  140.     r.port_ptr = &port;
  141.     r.xdr_results = xresults;
  142.     r.results_ptr = resultsp;
  143.     xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
  144.     if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
  145.         stat = RPC_CANTENCODEARGS;
  146.         goto done_broad;
  147.     }
  148.     outlen = (int)xdr_getpos(xdrs);
  149.     xdr_destroy(xdrs);
  150.     /*
  151.      * Basic loop: broadcast a packet and wait a while for response(s).
  152.      * The response timeout grows larger per iteration.
  153.      */
  154.     for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
  155.         for (i = 0; i < nets; i++) {
  156.             baddr.sin_addr = addrs[i];
  157.             if (sendto(sock, outbuf, outlen, 0,
  158.                 (struct sockaddr *)&baddr,
  159.                 sizeof (struct sockaddr)) != outlen) {
  160.                 perror("Cannot send broadcast packet");
  161.                 stat = RPC_CANTSEND;
  162.                 goto done_broad;
  163.             }
  164.         }
  165.         if (eachresult == NULL) {
  166.             stat = RPC_SUCCESS;
  167.             goto done_broad;
  168.         }
  169.     recv_again:
  170.         msg.acpted_rply.ar_verf = _null_auth;
  171.         msg.acpted_rply.ar_results.where = (caddr_t)&r;
  172.                 msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
  173.         readfds = mask;
  174.         switch (select(_rpc_dtablesize(), &readfds, (int *)NULL, 
  175.                    (int *)NULL, &t)) {
  176.  
  177.         case 0:  /* timed out */
  178.             stat = RPC_TIMEDOUT;
  179.             continue;
  180.  
  181.         case -1:  /* some kind of error */
  182.             if (errno == EINTR)
  183.                 goto recv_again;
  184.             perror("Broadcast select problem");
  185.             stat = RPC_CANTRECV;
  186.             goto done_broad;
  187.  
  188.         }  /* end of select results switch */
  189.     try_again:
  190.         fromlen = sizeof(struct sockaddr);
  191.         inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0,
  192.             (struct sockaddr *)&raddr, &fromlen);
  193.         if (inlen < 0) {
  194.             if (errno == EINTR)
  195.                 goto try_again;
  196.             perror("Cannot receive reply to broadcast");
  197.             stat = RPC_CANTRECV;
  198.             goto done_broad;
  199.         }
  200.         if (inlen < sizeof(u_long))
  201.             goto recv_again;
  202.         /*
  203.          * see if reply transaction id matches sent id.
  204.          * If so, decode the results.
  205.          */
  206.         xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
  207.         if (xdr_replymsg(xdrs, &msg)) {
  208.             if ((msg.rm_xid == xid) &&
  209.                 (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
  210.                 (msg.acpted_rply.ar_stat == SUCCESS)) {
  211.                 raddr.sin_port = htons((u_short)port);
  212.                 done = (*eachresult)(resultsp, &raddr);
  213.             }
  214.             /* otherwise, we just ignore the errors ... */
  215.         } else {
  216. #ifdef notdef
  217.             /* some kind of deserialization problem ... */
  218.             if (msg.rm_xid == xid)
  219.                 fprintf(stderr, "Broadcast deserialization problem");
  220.             /* otherwise, just random garbage */
  221. #endif
  222.         }
  223.         xdrs->x_op = XDR_FREE;
  224.         msg.acpted_rply.ar_results.proc = xdr_void;
  225.         (void)xdr_replymsg(xdrs, &msg);
  226.         (void)(*xresults)(xdrs, resultsp);
  227.         xdr_destroy(xdrs);
  228.         if (done) {
  229.             stat = RPC_SUCCESS;
  230.             goto done_broad;
  231.         } else {
  232.             goto recv_again;
  233.         }
  234.     }
  235. done_broad:
  236.     (void)close(sock);
  237.     AUTH_DESTROY(unix_auth);
  238.     return (stat);
  239. }
  240.  
  241.  
  242.